package com.linkhub.oms.admin.modules.stock.compute;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Map;
import java.util.Set;

/**
 * @Description: 库存计算执行器
 * @Author: echo
 * @Date: 2024/4/28 14:21
 * @Version: 1.0
 */
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StockComputeExecutor {

    private StockCreator stockCreator;

    private Map<String, Integer> skuPreemptionStockMap;

    private Set<String> outOfStockSkuIds;

    public static StockComputeExecutor create(StockCreator stockCreator) {
        return new StockComputeExecutor(stockCreator);

    }

    private StockComputeExecutor(StockCreator stockCreator) {
        this.stockCreator = stockCreator;
    }

    public StockComputeExecutor preemption() {
        this.skuPreemptionStockMap = Maps.newHashMap();
        this.outOfStockSkuIds = Sets.newHashSet();
        return this;
    }


    public boolean executePreemption(String skuId, Integer count) {
        return executePreemption(skuId, count, true);
    }

    public boolean executeMultiPreemption(Map<String, Integer> skuCountMap) {
        boolean preemption = true;
        for (Map.Entry<String, Integer> entry : skuCountMap.entrySet()) {
            preemption = preemption && executePreemption(entry.getKey(), entry.getValue(), false);
        }

        if (preemption) {
            skuCountMap.forEach((skuId, count) -> {
                Integer preemptionStock = skuPreemptionStockMap.getOrDefault(skuId, 0);
                skuPreemptionStockMap.put(skuId, preemptionStock + count);
            });

        }

        return preemption;
    }

    private boolean executePreemption(String skuId, Integer count, boolean accumulation) {
        if (outOfStockSkuIds.contains(skuId)) {
            return false;
        }

        Integer availableStock = stockCreator.getSkuAvailableStock(skuId);
        Integer preemptionStock = skuPreemptionStockMap.getOrDefault(skuId, 0);

        if (availableStock - preemptionStock - count >= 0) {
            if (accumulation) {
                skuPreemptionStockMap.put(skuId, preemptionStock + count);
            }

            return true;
        }

        outOfStockSkuIds.add(skuId);
        return false;
    }


}
